package com.hgicreate.app.md2docx.extension.kroki.internal;

import com.vladsch.flexmark.ast.FencedCodeBlock;
import com.vladsch.flexmark.docx.converter.*;
import com.vladsch.flexmark.docx.converter.internal.CoreNodeDocxRenderer;
import com.vladsch.flexmark.util.data.DataHolder;
import com.vladsch.flexmark.util.html.MutableAttributes;
import com.vladsch.flexmark.util.sequence.BasedSequence;
import org.docx4j.wml.R;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.*;

public class KrokiNodeDocxRender implements NodeDocxRenderer {
    DocxRendererOptions options;
    private final CoreNodeDocxRenderer coreNodeDocxRenderer;
    private int imageId = 200_000;
    private final KrokiClient krokiClient = new KrokiClient();

    public KrokiNodeDocxRender(DataHolder options) {
        coreNodeDocxRenderer = new CoreNodeDocxRenderer(options);
        this.options = new DocxRendererOptions(options);
    }

    @Override
    public Set<NodeDocxRendererHandler<?>> getNodeFormattingHandlers() {
        return new HashSet<>(Arrays.asList(
                new NodeDocxRendererHandler<>(FencedCodeBlock.class, KrokiNodeDocxRender.this::render)
        ));
    }

    @Override
    public Set<Class<?>> getNodeClasses() {
        return Set.of();
    }

    @Override
    public Set<Class<?>> getBookmarkWrapsChildrenClasses() {
        return Set.of();
    }

    private void render(FencedCodeBlock node, DocxRendererContext docx) {
        List<BasedSequence> lines = node.getContentLines();
        String content = String.join("\n", lines);
        try {
            BufferedImage img = krokiClient.parse(content);
            renderImage(img, docx);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    private R renderImage(BufferedImage image, DocxRendererContext docx) {
        MutableAttributes attributes = new MutableAttributes();
        int id1 = imageId++;
        int id2 = imageId++;
        String filenameHint = String.format(Locale.US, "Image%d", id1);
        int cx;

        if (image != null) {
            int width = image.getWidth();
            if (options.maxImageWidth > 0 && options.maxImageWidth < width) {
                cx = options.maxImageWidth;
                attributes.replaceValue("width", String.valueOf(cx));
            }

            return coreNodeDocxRenderer.newImage(docx, image, filenameHint, attributes, id1, id2, 1.0);
        }
        return null;
    }

    public static class Factory implements NodeDocxRendererFactory {

        @Override
        public NodeDocxRenderer create(DataHolder options) {
            return new KrokiNodeDocxRender(options);
        }
    }
}
